<template>
  <!-- 1. 搜索栏表单 -->
  <div class="form_box">
    <el-form :model="formData" ref="formRef" :inline="true">
      <el-form-item v-for="(item, index) in formOptions" :prop="item.prop" :key="index" :label="item.label ? item.label + '：' : ''">
        <!-- 1. 输入框 -->
        <template v-if="item.element === 'input'">
          <el-input v-model="formData[item.prop!]" :placeholder="item.placeholder ?? ''" />
        </template>
        <!-- 2. 下拉选择框 -->
        <template v-if="item.element === 'select'">
          <el-select v-model="formData[item.prop!]" :placeholder="item.placeholder ?? ''">
            <template v-for="option in item.options" :key="option.value">
              <el-option :label="option.label" :value="option.value" />
            </template>
          </el-select>
        </template>
      </el-form-item>
      <!-- 自定义插槽，可用于特殊表单块 -->
      <slot></slot>
    </el-form>
    <!-- 按钮组 -->
    <div class="btns">
      <el-button v-if="btnItems?.includes('search')" type="primary" :icon="Search" class="btn-search" @click="onSearchHandle">搜索</el-button>
      <el-button v-if="btnItems?.includes('export')" type="success" :icon="Document" class="btn-export" @click="onExportHandle">导出</el-button>
      <el-button v-if="btnItems?.includes('reset')" type="warning" :icon="RefreshLeft" class="btn-reset" @click="onResetHandle" :disabled="!isReset"
        >重置</el-button
      >
    </div>
  </div>
  <!-- 2. 表格 -->
  <el-table :data="props.data" border ref="tableRef" header-cell-class-name="table-header">
    <el-table-column type="selection"></el-table-column>
    <el-table-column
      v-for="item in props.structure"
      :key="item.label"
      :label="item.label"
      :align="item.center ? 'center' : ''"
      :min-width="item.width ? item.width : ''"
    >
      <!-- 图片类型 -->
      <template #default="scope" v-if="item.template.type === 'image'" :key="1">
        <el-image
          :src="scope.row[item.template.prop]"
          fit="contain"
          class="table-td-thumb"
          :z-index="10"
          :preview-src-list="[scope.row[item.template.prop]]"
          preview-teleported
        >
        </el-image>
      </template>
      <!-- 普通 文字 -->
      <template #default="scope" v-if="item.template.type === 'text'" :key="2">
        {{ scope.row[item.template.prop] }}
      </template>
      <!-- 带有表情的 文字 -->
      <template #default="scope" v-if="item.template.type === 'emoji'" :key="3">
        <span v-html="scope.row[item.template.prop].replace(/\#[\u4E00-\u9FA5]{1,3}\;/gi, formatEmoji)"></span>
      </template>
      <!-- 多个tag 标签文字类型 -->
      <template #default="scope" v-if="item.template.type === 'tag'" :key="4">
        <el-tag :type="item.color ?? ''" v-for="i in scope.row[item.template.prop]" :key="i.id" effect="dark">
          {{ i.name }}
        </el-tag>
      </template>
      <!-- 单个tag 标签文字类型 -->
      <template #default="scope" v-if="item.template.type === 'label'" :key="5">
        <el-tag :type="item.color ?? ''" effect="dark">
          {{ scope.row[item.template.prop] }}
        </el-tag>
      </template>
      <!-- 状态 文字类型 -->
      <template #default="scope" v-if="item.template.type === 'state'" :key="6">
        <el-tag :type="scope.row['state'] ?? ''" effect="dark">
          {{ scope.row[item.template.prop] }}
        </el-tag>
      </template>
      <!-- 开关类型 -->
      <template #default="scope" v-if="item.template.type === 'switch'" :key="7">
        <el-switch v-model="scope.row[item.template.prop]" @change="switchChange(scope.row, item.template.prop)" :validate-event="false" />
      </template>
    </el-table-column>
    <!-- 按钮 操作 -->
    <el-table-column label="操作" align="center" min-width="150" v-if="action" :key="8">
      <template #default="scope">
        <slot name="operation" :scope="scope"></slot>
      </template>
    </el-table-column>
  </el-table>
  <el-pagination
    class="pagination"
    v-model:current-page="currentPage"
    v-model:page-size="pageSize"
    layout="prev, pager, next, jumper"
    :total="total"
    @current-change="handleCurrentChange"
  />
</template>

<script lang="ts" setup name="baseTable">
  import { ref, reactive } from 'vue'
  import { useRoute } from 'vue-router'
  import { exportExcel } from '@/utils/export'
  import { removeEmptyValues } from '@/utils/removeEmptyValues'
  import formatEmoji from '@/utils/formatEmoji'
  import type { FormInstance } from 'element-plus'
  import type { FormRules } from 'element-plus'
  import notification from '@/utils/notification'
  import { Document, RefreshLeft, Search } from '@element-plus/icons-vue'

  interface IformOptions {
    label: string // label文字
    prop: string // 字段名
    element: string // 指定组件
    initValue?: string // 字段初始值
    placeholder?: string // elementplus组件属性
    rules?: FormRules // elementplus组件校验规则
    events?: any // elementplus组件方法
    options?: { label: string; value: string | number | boolean }[]
  }
  interface IProps {
    data: any // 数据
    structure: any // 结构
    total?: number // 数据总条数
    action?: boolean // 是否需要展示操作选项
    formOptions?: IformOptions[]
    btnItems?: string // 按钮组
    // pageSize?: number // 每页多少条数据
    // currentPage?: number  // 当前页数
  }

  const props = withDefaults(defineProps<IProps>(), {
    action: true,
  })
  const route = useRoute()

  const pageSize = ref<number>(7)
  const currentPage = ref<number>(1)
  const emits = defineEmits(['switchChange', 'currentPageChange', 'onSearch', 'onReset'])
  const formRef = ref<FormInstance>()
  const tableRef = ref<any>()
  let formData = reactive<any>({}) // 表单初始化数据对象
  const initFormValue = () => {
    props.formOptions?.forEach((v: any) => {
      formData[v.prop] = v.initValue || ''
    })
  }
  const isReset = ref(false)
  initFormValue()

  // 校验
  const onValidate = (callback: Function) => {
    if (!formRef.value) return
    formRef.value.validate(valid => {
      if (valid) {
        callback()
      }
    })
  }

  // 搜索
  const onSearchHandle = () => {
    onValidate(() => {
      const unEmptyFormData = removeEmptyValues(formData)
      if (Object.keys(unEmptyFormData).length === 0) return notification.warning('至少选择一个字段进行搜索~')
      emits('onSearch', unEmptyFormData)
      isReset.value = true
    })
  }

  // 导出
  const onExportHandle = () => {
    onValidate(() => {
      exportExcel(props.data, route.meta.title as string)
    })
  }

  // 重置
  const onResetHandle = () => {
    if (formRef.value) {
      currentPage.value = 1 // currentPage 重置为1
      formRef.value.resetFields()
      emits('onReset')
    }
  }

  const handleCurrentChange = (value: number) => {
    emits('currentPageChange', value)
  }

  const switchChange = (row: any, prop: any) => {
    emits('switchChange', row, prop)
  }
</script>

<style scoped lang="less">
  .form_box {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
    .btns {
      margin-right: 15px;
    }
  }
  .pagination {
    display: flex;
    justify-content: center;
    margin: 12px 0;
  }
</style>
